#include <video.h>
#include <portio.h>
#include <system.h>

void clear_screen() {
  memsetw((void*)ADDRESS_VIDEO, char_entry(FONT_DEFAULT, ' '), COLS_MAX * ROWS_MAX); 
}

uint16_t get_cursor() {
  port_byte_out(REG_SCREEN_CTRL, 14);
  uint16_t offset = port_byte_in(REG_SCREEN_DATA) << 8;
  port_byte_out(REG_SCREEN_CTRL, 15);
  offset += port_byte_in(REG_SCREEN_DATA);
  return offset*2;
}

void set_cursor(uint16_t offset) {
  offset /= 2;
  port_byte_out(REG_SCREEN_CTRL, 0x0F);
  port_byte_out(REG_SCREEN_DATA, (uint8_t) (offset & 0xFF));
  port_byte_out(REG_SCREEN_CTRL, 0x0E);
  port_byte_out(REG_SCREEN_DATA, (uint8_t) ((offset >> 8) & 0xFF));
}

void print_char(char character, uint8_t type, int row, int col) {
  int offset;
  if (row < 0 || col < 0) {
    offset = get_cursor();
  } else {
    offset = get_screen_offset(row, col);
  }
  if (character == '\n') {
    int rows = offset / (2 * COLS_MAX);
    offset = get_screen_offset(rows, COLS_MAX - 1);
  } else {
    char* vidmem = (char*) ADDRESS_VIDEO;
    if (!type) {
      type = FONT_DEFAULT;
    }
    vidmem[offset] = character;
    vidmem[offset + 1] = type;
  }
  offset += 2;
  set_cursor(offset);
} 

void print_string(char* str, uint8_t type, int row, int col) {
  size_t i, offset;
  if (row < 0 || col < 0) {
    offset = get_cursor();
  } else {
    offset = get_screen_offset(row, col);
  }
  if (!type) {
    type = FONT_DEFAULT;
  }
  char* vidmem = (char*) ADDRESS_VIDEO;
  for(i = 0; i < strlen(str); i++) {
    if (str[i] == '\n') {
      int rows = offset / (2 * COLS_MAX);
      offset = get_screen_offset(rows, COLS_MAX - 1);
    } else {
      vidmem[offset] = str[i];
      vidmem[offset + 1] = type;
    }
    offset += 2;
  }
  set_cursor(offset);
}

void scroll(int rows) {
  memcpyw(
    (void*) ADDRESS_VIDEO, 
    (void*) ADDRESS_VIDEO + COLS_MAX * rows * 2, 
    COLS_MAX * (ROWS_MAX - rows) * 2
  );
  memsetw(
    (void*) ADDRESS_VIDEO + COLS_MAX * (ROWS_MAX - rows) * 2,
    char_entry(FONT_DEFAULT, ' '),
    rows * COLS_MAX
  );
}
